/*
 * @Author: wwssaabb
 * @Date: 2021-11-10 16:12:45
 * @LastEditTime: 2021-12-17 09:35:38
 * @FilePath: \handwritten-code\main\promise.js
 */

//三个状态
const PENDING = 'pending' //等待
const FULFILLED = 'fulfilled' //完成
const REJECTED = 'rejected' //失败


class MyPromise {
  constructor(executor) {
    //捕获执行器错误
    try {
      executor(this.resolve, this.reject)
    } catch (error) {
      this.reject(error)
    }
  }
  //初始化状态
  state = PENDING
  value = null
  reason = null
  onFulfilledCallbacks = []
  onRejectedCallbacks = []

  //改变为成功状态
  resolve(value) {
    if (this.state === PENDING) {
      this.state = FULFILLED
      this.value = value
      //将成功的回调队列进行遍历执行
      while (this.onFulfilledCallbacks.length) {
        this.onFulfilledCallbacks.shift()(value)
      }
    }
  }

  //改变为失败状态
  reject(reason) {
    if (this.state === PENDING) {
      this.state = REJECTED
      this.reason = reason
      //将失败的回调队列进行遍历执行
      while (this.onRejectedCallbacks.length) {
        this.onRejectedCallbacks.shift()(reason)
      }
    }
  }

  //.then回调，注册一个一个异任务
  then(onFulfilled, onRejected) {
    //初始化回调参数
    onFulfilled = onFulfilled ? onFulfilled : val => val
    onRejected = onRejected ? onRejected : err => {
      throw err
    }

    //模拟异步任务，使用queueMicrotask模拟微任务
    const self = new MyPromise((resolve, reject) => {
      const fulfilledMicrotask = () => {
        queueMicrotask(() => {
          try {
            resolvePromise(onFulfilled(this.value), self, resolve, reject)
          } catch (error) {
            reject(error)
          }
        })
      }
      const rejectedMicrotask = () => {
        queueMicrotask(() => {
          try {
            resolvePromise(onRejected(this.reason), self, resolve, reject)
          } catch (error) {
            reject(error)
          }
        })
      }

      if (this.state === FULFILLED) fulfilledMicrotask()
      if (this.state === REJECTED) rejectedMicrotask()
      if (this.state === PENDING) {
        //如果是等待的状态则存储起来
        this.onFulfilledCallbacks.push(fulfilledMicrotask)
        this.onRejectedCallbacks.push(rejectedMicrotask)
      }
    })
    return self
  }
}


function resolvePromise(instance, self, resolve, reject) {
  //判断自己
  if (instance === self) {
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }

  //promiseA+规范要求需要判断instance为object和function的处理
  if (typeof instance === 'object' || typeof instance === 'function') {
    //instance 为null的情况
    if (instance === null) return resolve(instance)

    let then
    try {
      //把instance.then赋值给then
      then = instance.then
    } catch (error) {
      //报错则用error拒绝promise
      reject(error)
    }

    //如果then是函数
    if (typeof then === 'function') {
      //执行状态
      let called = false
      try {
        //then指向instance
        then.call(instance, x => {
          if (called) return
          called = true
          resolvePromise(instance, x, resolve, reject)
        }, y => {
          if (called) return
          called = true
          reject(y)
        })
      } catch (error) {
        if (called) return
        called = true
        reject(error)
      }
    } else {
      resolve(instance)
    }
  } else {
    //如果不是promise的实例，则直接返回这个结果的promise
    resolve(instance)
  }
}